package FTPUpload.agent;

import jetbrains.buildServer.agent.*;
import jetbrains.buildServer.util.StringUtil;
import org.apache.commons.net.*;
import org.jetbrains.annotations.*;


import java.io.*;
import org.apache.commons.net.ftp.*;

public class FTPBuildProcess extends FutureBasedBuildProcess implements ProtocolCommandListener
{
    private final AgentRunningBuild myBuild;
    private final BuildRunnerContext myContext;
    private BuildProgressLogger logger;

    public FTPBuildProcess(@NotNull final AgentRunningBuild build, @NotNull final BuildRunnerContext context)
    {
        myBuild = build;
        myContext = context;
    }

    private String getParameter(@NotNull final String parameterName)
    {
        final String value = myContext.getRunnerParameters().get(parameterName);
        if (value == null || value.trim().length() == 0) return null;
        String result = value.trim();
        return result;
    }

    @NotNull
    public BuildFinishedStatus call() throws Exception
    {
        BuildFinishedStatus toReturn = BuildFinishedStatus.FINISHED_FAILED;

        logger = myBuild.getBuildLogger();
        String folderPath = getParameter("folderPath");
        String address = getParameter("address");
        String remoteFolder = getParameter("remoteFolder");
        String username = getParameter("username");
        String password = getParameter("password");

        logger.progressMessage("FolderPath: " + folderPath);
        logger.progressMessage("RemoteFolderPath: " + remoteFolder);
        logger.progressMessage("Address: " + address);
        logger.progressMessage("Username: " + username);
        logger.progressMessage("Password: " + password);
        logger.progressMessage("Connecting to FTP Server...");


        File dir = new File(folderPath);

        FTPClient client = new FTPClient();
        client.addProtocolCommandListener(this);
        client.connect(address);
        logger.progressMessage("Logging In...");

        if(client.login(username, password))
        {
            logger.progressMessage("Login Success! Entering Passive Mode..");
            client.enterLocalPassiveMode();
            client.changeWorkingDirectory(remoteFolder);
            DoUpload("", client, dir);
            return BuildFinishedStatus.FINISHED_SUCCESS;
        }
        else
        {
            logger.progressMessage("Unable to login!");
        }

        if(client.isConnected())
            client.disconnect();

        return toReturn;
    }

    private void DoUpload(String relativePath, FTPClient client, File currDirectory) throws Exception
    {
        String[] entries = currDirectory.list();
        byte[] buffer = new byte[4096]; // Create a buffer for copying
        int bytesRead;

        if(!StringUtil.isEmpty(relativePath))
        {
            String folderName = currDirectory.getName();
            logger.progressMessage("Changing Remote Path To: " + folderName);

            if(!client.changeWorkingDirectory(folderName))
            {
                logger.progressMessage("Creating Remote Path: " + folderName);
                client.makeDirectory(folderName);
                if(!client.changeWorkingDirectory(folderName))
                {
                    throw new Exception("Unable to create remote structure!");
                }
            }
        }

        logger.progressMessage("Working On: " + currDirectory.getAbsolutePath());
        for (int i = 0; i < entries.length; i++)
        {
            File f = new File(currDirectory, entries[i]);
            if (f.isDirectory())
            {
                DoUpload(relativePath + f.getName() + "/", client, f);
                client.changeWorkingDirectory("..");
            }
            else
            {
                String path = "";
                if(relativePath.trim().length() == 0)
                    path = f.getName();
                else
                    path = relativePath + f.getName();

                FileInputStream in = new FileInputStream(f); // Stream to read file
                logger.progressMessage("Uploading File: " + path);
                client.storeFile(f.getName(), in);
                in.close();
            }
        }
    }

    public void protocolCommandSent(ProtocolCommandEvent protocolCommandEvent)
    {

    }

    public void protocolReplyReceived(ProtocolCommandEvent protocolCommandEvent)
    {
        logger.progressMessage(protocolCommandEvent.getMessage());
    }
}
